﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;

namespace Roton2.TextModeEmulation
{
    /// <summary>
    /// Allows direct 32-bit PArgb pixel access in a managed bitmap.
    /// </summary>
    public class PixelBuffer
    {
        private Bitmap bitmap;
        private Int32[] bits;
        private GCHandle bitsHandle;
        private IntPtr bitsScan0;
        private int height;
        private int width;

        /// <summary>
        /// Create a pixel buffer with the specified width and height.
        /// </summary>
        public PixelBuffer(int width, int height)
        {
            bits = new Int32[width * height];
            InitializeBitmap(width, height);
        }

        /// <summary>
        /// Create a pixel buffer with the specified width, height and raw bitmap data.
        /// </summary>
        public PixelBuffer(int width, int height, int[] bits)
        {
            this.bits = bits;
            InitializeBitmap(width, height);
        }

        ~PixelBuffer()
        {
            if (bitsHandle.IsAllocated)
                bitsHandle.Free();
        }

        /// <summary>
        /// Managed Bitmap object that contains the raw bitmap data.
        /// </summary>
        public Bitmap Bitmap
        {
            get
            {
                return bitmap;
            }
        }

        /// <summary>
        /// Raw PArgb bitmap data.
        /// </summary>
        public Int32[] Bits
        {
            get
            {
                return bits;
            }
        }

        /// <summary>
        /// Initialize bitmap data.
        /// </summary>
        void InitializeBitmap(int width, int height)
        {
            this.width = width;
            this.height = height;
            bitsHandle = GCHandle.Alloc(bits, GCHandleType.Pinned);
            bitsScan0 = bitsHandle.AddrOfPinnedObject();
            bitmap = new Bitmap(width, height, width * 4, PixelFormat.Format32bppPArgb, bitsScan0);
        }

        /// <summary>
        /// Height of the bitmap, in bits.
        /// </summary>
        public int Height
        {
            get
            {
                return height;
            }
        }

        /// <summary>
        /// Managed pointer to the raw bitmap data.
        /// </summary>
        public IntPtr Scan0
        {
            get
            {
                return bitsScan0;
            }
        }

        /// <summary>
        /// Width of the bitmap, in pixels.
        /// </summary>
        public int Width
        {
            get
            {
                return width;
            }
        }
    }
}
